package com.yuye.excel.easyexcel.handle.listener;

import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.excel.exception.ExcelAnalysisException;
import com.alibaba.excel.exception.ExcelDataConvertException;
import com.alibaba.excel.read.metadata.holder.ReadRowHolder;
import com.alibaba.excel.util.StringUtils;
import com.yuye.excel.base.config.LanguageTransformationHandler;
import com.yuye.excel.easyexcel.handle.dto.ExcelCheckErrDto;
import com.yuye.excel.easyexcel.handle.dto.ExcelCheckResult;
import com.yuye.excel.easyexcel.handle.vali.EasyExcelValiHelper;
import com.yuye.excel.easyexcel.handle.vali.ExcelCheckManager;
import com.yuye.excel.enums.ExcelLanguageConstant;
import com.yuye.excel.utils.EasyExcelUtils;
import com.yuye.excel.utils.JsonUtil;

import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.Field;
import java.util.*;


@Data
@EqualsAndHashCode(callSuper = false)
@Slf4j
public class EasyExcelListener<T> extends AnalysisEventListener<T> {

	private List<T> successList = new ArrayList<>();

	private List<ExcelCheckErrDto<T>> errList = new ArrayList<>();

	private ExcelCheckManager<T> excelCheckManager;

	private List<T> list = new ArrayList<>();
	
	private String fileName;

	private Class<T> clazz;
	
	public EasyExcelListener() {
		
	}

	public EasyExcelListener(ExcelCheckManager<T> excelCheckManager) {
		this.excelCheckManager = excelCheckManager;
	}

	public EasyExcelListener(ExcelCheckManager<T> excelCheckManager, Class<T> clazz) {
		this.excelCheckManager = excelCheckManager;
		this.clazz = clazz;
	}
	
	public EasyExcelListener(ExcelCheckManager<T> excelCheckManager, Class<T> clazz, String fileName) {
		this.excelCheckManager = excelCheckManager;
		this.clazz = clazz;
		this.fileName = fileName;
	}

	@Override
	public void invoke(T t, AnalysisContext analysisContext) {
		String errMsg;
		List<List<String>> errMsgList = null;
		try {
			errMsgList = EasyExcelValiHelper.validateEntity(t);
		} catch (NoSuchFieldException e) {
			errMsg = "解析数据出错";
			e.printStackTrace();
		}
		if (errMsgList != null && errMsgList.size() > 0) {
			errMsg = toOtherLanguage(errMsgList);
			if(!StringUtils.isEmpty(fileName)) {
				errMsg = fileName + "  " + errMsg;
			}
			ExcelCheckErrDto excelCheckErrDto = new ExcelCheckErrDto(t, errMsg);
			errList.add(excelCheckErrDto);
		} else {
			list.add(t);
		}
		if (list.size() > 1000) {
			ExcelCheckResult result = excelCheckManager.checkImportExcel(list);
			successList.addAll(result.getSuccessDtos());
			errList.addAll(result.getErrDtos());
			list.clear();
		}
	}
	
	private String toOtherLanguage(List<List<String>> errMsgList) {
		String errMsg ;
		
		//语种转换
		errMsg = LanguageTransformationHandler.transformation(excelCheckManager, errMsgList);
		return errMsg;
	}
	

	@Override
	public void doAfterAllAnalysed(AnalysisContext analysisContext) {
		ExcelCheckResult result = excelCheckManager.checkImportExcel(list);

		successList.addAll(result.getSuccessDtos());
		errList.addAll(result.getErrDtos());
		list.clear();
	}

	
	@Override
	public void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) {
		String sheetName = context.readSheetHolder().getSheetName();
		Object currentRowAnalysisResult = context.getCurrentRowAnalysisResult();
		ReadRowHolder readRowHolder = context.readRowHolder();
		Integer rowIndex = readRowHolder.getRowIndex();
		super.invokeHeadMap(headMap, context);
		log.info("表头：[{}] 行 [{}]", rowIndex, JsonUtil.toJson(headMap));
		if (clazz != null) {
			try {
				Map<Integer, String> indexNameMap = getIndexNameMap(clazz, rowIndex);
				Set<Integer> keySet = indexNameMap.keySet();
				for (Integer key : keySet) {
					if(headMap.get(key) == null) {
						headMap.put(key, "");
					}
					if (!indexNameMap.get(key).equals(headMap.get(key)) && !"".equals(indexNameMap.get(key))) {
						throw new ExcelAnalysisException(EasyExcelUtils.getExcelErrorMsgByForamt(sheetName, rowIndex, key, "%s 中 第 %s 行 %s 列 解析excel出错，请传入正确格式的excel 应该为: " + indexNameMap.get(key)));
					}
				}

			} catch (NoSuchFieldException e) {
				e.printStackTrace();
			}
		}
	}

	@Override
	public void onException(Exception exception, AnalysisContext context) throws Exception {
		super.onException(exception, context);
		log.error(exception.toString());
		if (exception instanceof ExcelDataConvertException) {
			ExcelDataConvertException excelDataConvertException = (ExcelDataConvertException) exception;
			log.error("第{}行，第{}列解析异常", excelDataConvertException.getRowIndex(),
					excelDataConvertException.getColumnIndex());
		}
	}

	
	@SuppressWarnings("rawtypes")
	public Map<Integer, String> getIndexNameMap(Class clazz, Integer rowIndex) throws NoSuchFieldException {
		Map<Integer, String> result = new HashMap<>();
		Field field;
		Field[] fields = clazz.getDeclaredFields();
		for (int i = 0; i < fields.length; i++) {
			field = clazz.getDeclaredField(fields[i].getName());
			field.setAccessible(true);
			ExcelProperty excelProperty = field.getAnnotation(ExcelProperty.class);
			if (excelProperty != null) {
				int index = excelProperty.index();
				String[] values = excelProperty.value();
				StringBuilder value = new StringBuilder();

				if(rowIndex != 0) {
					if(values[rowIndex].equals(values[rowIndex - 1])) {
						value.append("");
						result.put(index, value.toString());
						continue;
					}
				}
				value.append(values[rowIndex]);
				result.put(index, value.toString());
			}
		}
		return result;
	}



}
